﻿// MnemonicStackTest.cs
//
// Copyright 2008 by Burt Harris
// Licensed under the Microsoft Public License (Ms-PL)
// See: http://www.codeplex.com/yaml/license
//

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace YaTools.Yaml.UnitTests
{
    /// <summary>
    ///This is a test class for MnemonicStackTest and is intended
    ///to contain all MnemonicStackTest Unit Tests
    ///</summary>
    [TestClass]
    public class MnemonicStackTest
    {
        private static readonly int[] Array123 = new[] {1, 2, 3};
        private static readonly int[] ArrayEmpty = new int[0];
        private MnemonicStack<int> _target;

        [TestInitialize]
        public void Push123()
        {
            if (_target == null) _target = new MnemonicStack<int>();
            _target.Push(1);
            _target.Push(2);
            _target.Push(3);
        }

        public void Pop321()
        {
            Assert.AreEqual(3, _target.Pop());
            Assert.AreEqual(2, _target.Pop());
            Assert.AreEqual(1, _target.Pop());
        }

        public void Push456()
        {
            _target.Push(4);
            _target.Push(5);
            _target.Push(6);
        }

        public void Pop654()
        {
            Assert.AreEqual(6, _target.Pop());
            Assert.AreEqual(5, _target.Pop());
            Assert.AreEqual(4, _target.Pop());
        }


        [TestMethod]
        public void CountTest()
        {
            Assert.AreEqual(3, _target.Count);
        }

        [TestMethod]
        public void PopCountTest()
        {
            Pop321();
            Assert.AreEqual(0, _target.Count);
        }

        [TestMethod]
        public void TrimExcessTest()
        {
            short l = _target.Memorize(888);
            _target.Clear();
            short m = _target.Memorize(888);
            PushMany();
            short n = _target.Memorize(888);
            Assert.AreEqual(888, _target.Recall(l));
            Assert.AreEqual(3, _target.Count);
            Assert.AreEqual(888, _target.Recall(m));
            Assert.AreEqual(0, _target.Count);
            Assert.AreEqual(888, _target.Recall(n));
            Assert.AreEqual(20000, _target.Count);
            _target.Clear();
            short m2 = _target.Memorize(888);
            Assert.AreEqual(m, m2);
            _target.Clear();
            _target.TrimExcess();
            short m3 = _target.Memorize(888);
            Assert.AreNotEqual(m, m3);
            Push123();
            short l2 = _target.Memorize(888);
            Assert.AreEqual(888, _target.Recall(m3));
            Assert.AreEqual(0, _target.Count);
            Assert.AreEqual(888, _target.Recall(l2));
            Assert.AreEqual(3, _target.Count);
            Pop321();
            Assert.AreEqual(0, _target.Count);
        }

        private void PushMany()
        {
            for (int i = 0; i < 20000; i++)
                _target.Push(i);
        }

        [TestMethod]
        public void ToArrayTest()
        {
            CollectionAssert.AreEqual(Array123, _target.ToArray());
            Pop321();
            CollectionAssert.AreEqual(ArrayEmpty, _target.ToArray());
        }

        [TestMethod]
        public void RememberTest()
        {
            short mnemonic = _target.Memorize(4);
            Pop321();
            Assert.AreEqual(4, _target.Recall(mnemonic));
            Pop321();
            CollectionAssert.AreEqual(ArrayEmpty, _target.ToArray());
        }

        [TestMethod]
        public void PeekTest()
        {
            Assert.AreEqual(3, _target.Peek());
        }

        [TestMethod]
        public void CopyToTest()
        {
            var data = new int[3];
            _target.CopyTo(data, 0);
            CollectionAssert.AreEqual(Array123, data);
        }

        [TestMethod]
        public void ContainsTest()
        {
            Assert.IsTrue(_target.Contains(1));
            Assert.IsTrue(_target.Contains(2));
            Assert.IsTrue(_target.Contains(3));
            Pop321();
            Assert.IsFalse(_target.Contains(1));
            Assert.IsFalse(_target.Contains(2));
            Assert.IsFalse(_target.Contains(3));
        }

        [TestMethod]
        public void ContainsTest2()
        {
            short mnemonic = _target.Memorize(1234);
            ContainsTest();
            Assert.AreEqual(1234, _target.Recall(mnemonic));
            ContainsTest();
        }

        [TestMethod]
        public void ClearTest()
        {
            _target.Clear();
            Assert.AreEqual(0, _target.Count);
        }
    }
}